#include "network.h"

cNetwork::cNetwork()
{
    //ctor
if(SDLNet_Init()==-1) {//Start SDL_NET
cout << "SDLNet_TCP_INIT: \n " << SDLNet_GetError();
exit(2);
}

//Clean thread variables
MasterThread = NULL;
ClientsLock = NULL;
ClientsLock = SDL_CreateSemaphore( 1 );//semafor protector, previene que mas de un thread vuelque información a la vez a la cola
}

cNetwork::~cNetwork()
{
    //dtor
SDLNet_TCP_Close(ServerSock);//Close socket
SDLNet_Quit();//Close SDL_NET
}


void cNetwork::CleanClient(unsigned int Client)//clean a client so we can use it
{
//cout << "cleaning client: " << Client << endl;
Clients[Client]->UID =Client;
Clients[Client]->socket = NULL;
Clients[Client]->_server = myserver;
Clients[Client]->Connected = false;
Clients[Client]->Login = false;
}

void cNetwork::Start(Uint16 MAXUsers, Uint16 Port)
{

//1-initialize MAXUsers clients
//2-Start sock server

unsigned int x;
for (x=1;x<=MAXUsers;x++)
{
Clients.push_back(new cClient());//insert a new client into the clients vector
CleanClient(Clients.size() -1);
}

cout << "OPENING SERVER SOCKET... " << endl;
if(SDLNet_ResolveHost(&ip,NULL,Port)==-1) {
cout << "SDLNet_TCP_ResolveHost:" << endl  << SDLNet_GetError();
exit(1);
}

ServerSock=SDLNet_TCP_Open(&ip);
if(!ServerSock) {
cout << "SDLNet_TCP_open: " << endl << SDLNet_GetError();
exit(2);
}

ShutDown = false;
//Create and run the threads
MasterThread = SDL_CreateThread( &Master, this );

}



int cNetwork::Master( void *data )//Master listener function/thread
{
TCPsocket new_tcpsock; //Temporary socket to store incoming connections
new_tcpsock=NULL;

cout << "Waiting for incoming connections... " << endl;

bool doneMain=false;
while(!doneMain)//MAIN LOOP
    {
    if(!new_tcpsock)//We have a new client incoming
    {
        new_tcpsock=SDLNet_TCP_Accept(((cNetwork*)data)->ServerSock); // accept a connection coming in on server_tcpsock
        SDL_Delay(5);//No new clients, wait a little
    }else{
        cout << "New client incoming..." << endl;
        unsigned int x;
        for(x=0;x<((cNetwork*)data)->Clients.size();x++)
        {
        if (((cNetwork*)data)->Clients[x]->Connected==false)
            {
            ((cNetwork*)data)->CleanClient(x);
            ((cNetwork*)data)->Clients[x]->socket=new_tcpsock;//asign the socket
            ((cNetwork*)data)->Clients[x]->Connected = true;
            ((cNetwork*)data)->Clients[x]->Login = false;
            ((cNetwork*)data)->Clients[x]->StartThreads();//start client listener thread
            break;
            }
    }//for
        new_tcpsock=NULL;//release temporary socket var

        }//if new data

if (((cNetwork*)data)->ShutDown==true)doneMain =true;

}//while
cout << "Exiting Main thread..." << endl;
return 0;
}

void cNetwork::ClearClients()//Clear disconnected clients
{
unsigned int x;
bool done = false;
//SDL_SemWait(ClientsLock);
if (Clients.size()>0)
{
x=0;
while (!done)
{
 if (!Clients[x]->Connected)
            {
            Clients.erase(Clients.begin()+x);
           // cout << "Number of clients:" << Clients.size() << endl;
            if (x>0)x--;
            }//if !connected
x++;
if(x>=Clients.size())done=true;
}
}//clients size

}

void cNetwork::Finish()
{
    ShutDown =true;
    SDL_WaitThread(MasterThread,&threadReturnMaster);
    unsigned int x;
    for(x=0;x<Clients.size();x++)
        {
            Clients[x]->Connected=false;//force disconnection
        }//for

    while (Clients.size()>0)
        {
            ClearClients();
        }
}
